/**
 * @file 单例化装饰器
 * @author DuskyHuang 圣子
*/

import { Component } from "cc";
import { swapper } from "./swapper";

/** 单例类装饰器 */
export const singleton: DecoratorSwapper<ClassDecorator, []> =
    swapper<ClassDecorator>(<T extends Function>([ctor]: [T]) => {
        // 为Component类型设置唯一instance
        if (_isSubOf(ctor as any, Component)) {
            const _ = ctor.prototype;
            const onLoad = _.onLoad;
            Object.defineProperty(_, 'onLoad', {
                configurable: true, enumerable: false,
                value: function () {
                    ctor['_instance'] = this;
                    Function.invoke(onLoad, this);
                }
            });
        }
        return Object.defineProperty(ctor, 'instance', {
            configurable: true, enumerable: true,
            get: function () {
                if (!this._instance || !(this._instance instanceof this)) {
                    this._instance = new this();
                }
                return this._instance;
            }
        }) as T & { readonly instance: T };
    });

function _isSubOf(sub: Class<any>, base: Class<any>): boolean {
    return Object.getPrototypeOf(sub) === base || sub.prototype instanceof base;
}